package com.itbaizhan.myconsumer1;

import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import java.io.IOException;
//手动签收消息，防止消息丢失，没有成功签收就会返回队列
@Component
public class AckConsumer {
    //测试OocConsumer,java 所以注释
  // @RabbitListener(queues = "my_queue")
    /*信道channel 用于手动签收
    * 参数导的包是含有 amqp*/
    public void listerMessage(Message message, Channel channel) throws IOException, InterruptedException {
        //消息投递序号，消息每一次投递该值都会+1
        long deliveryTag = message.getMessageProperties().getDeliveryTag();
        try{
            //int i = 1/0;  //模拟处理消息出现bug
            System.out.println("成功接收信息："+message);
            /*签收消息
            * 参数1： 消息投递序号
            * 参数2：是否一次可以签收多条消息*/
            channel.basicAck(deliveryTag,true);
        }catch (Exception e){
            System.out.println("消息发送失败！");
            Thread.sleep(3000);  //休息3秒
            /*
            * 参数1： 消息投递序号
            * 参数2：是否一次可以拒签多条消息
            * 参数3：拒签后是否返回队列*/
            channel.basicNack(deliveryTag,true,true);
        }

    }
}

/*在RabbitMQ中，消费者接收到消息后会向队列发送确认签收的消息，
只有确认签收的消息才会被移除队列。这种机制称为消费者消息确认
（Consumer Acknowledge，简称Ack）。类似快递员派送快递也需要我们签收，
否则一直存在于快递公司的系统中。

消息分为自动确认和手动确认。自动确认指消息只要被消费者接收到，
无论是否成功处理消息，则自动签收，并将消息从队列中移除。但是在 实际开发中，
收到消息后可能业务处理出现异常，那么消息就会丢失。此时需要设置手动签收，
即在业务处理成功再通知签收消息，如果出现异常，则拒签消息，
让消息依然保留在队列当中。

自动确认：spring.rabbitmq.listener.simple.acknowledge="none"
手动确认：spring.rabbitmq.listener.simple.acknowledge="manual"
消费者配置开启手动签收

spring:
  rabbitmq:
   host: 192.168.0.162
   port: 5672
   username: itbaizhan
   password: itbaizhan
   virtual-host: /
  # 开启手动签收
   listener:
    simple:
     acknowledge-mode: manual*/